package com.wenlin.myproduction.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.wenlin.myproduction.R;
import com.wenlin.myproduction.util.Checker;
import com.wenlin.myproduction.util.LogUtils;
import com.wenlin.myproduction.util.UI;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 文琳
 * @time 2020/8/12 9:52
 * @desc 计分板控件，显示指定数字的图片版，仅支持非负整数（正整数和0）。支持蓝色（默认）和红色，小号（默认）和大号图片。图片大小不可设置。
 */
public class PicNumberView extends View {
    public static final int[] NUMBER_BLUE_PIC_RES_ID = {R.mipmap.pk_ic_0_blue, R.mipmap.pk_ic_1_blue, R.mipmap.pk_ic_2_blue, R.mipmap.pk_ic_3_blue,
            R.mipmap.pk_ic_4_blue, R.mipmap.pk_ic_5_blue, R.mipmap.pk_ic_6_blue, R.mipmap.pk_ic_7_blue,
            R.mipmap.pk_ic_8_blue, R.mipmap.pk_ic_9_blue};
    public static final int[] NUMBER_RED_PIC_RES_ID = {R.mipmap.pk_ic_0_red, R.mipmap.pk_ic_1_red, R.mipmap.pk_ic_2_red, R.mipmap.pk_ic_3_red,
            R.mipmap.pk_ic_4_red, R.mipmap.pk_ic_5_red, R.mipmap.pk_ic_6_red, R.mipmap.pk_ic_7_red,
            R.mipmap.pk_ic_8_red, R.mipmap.pk_ic_9_red};
    public static final int[] NUMBER_BLUE_BIG_PIC_RES_ID = {R.mipmap.pk_ic_0_blue_big, R.mipmap.pk_ic_1_blue_big, R.mipmap.pk_ic_2_blue_big, R.mipmap.pk_ic_3_blue_big,
            R.mipmap.pk_ic_4_blue_big, R.mipmap.pk_ic_5_blue_big, R.mipmap.pk_ic_6_blue_big, R.mipmap.pk_ic_7_blue_big,
            R.mipmap.pk_ic_8_blue_big, R.mipmap.pk_ic_9_blue_big};
    public static final int[] NUMBER_RED_BIG_PIC_RES_ID = {R.mipmap.pk_ic_0_red_big, R.mipmap.pk_ic_1_red_big, R.mipmap.pk_ic_2_red_big, R.mipmap.pk_ic_3_red_big,
            R.mipmap.pk_ic_4_red_big, R.mipmap.pk_ic_5_red_big, R.mipmap.pk_ic_6_red_big, R.mipmap.pk_ic_7_red_big,
            R.mipmap.pk_ic_8_red_big, R.mipmap.pk_ic_9_red_big};
    private static final long ANIM_DUR = 1000;
    private int viewWidth, viewHeight;
    private int singleNumberWidth, singleNumberHeight;
    private int number;
    private boolean isRed;
    private boolean isBig;
    private Paint paint;
    private Bitmap[] arrBitmap = new Bitmap[10];
    private List<String> current;
    private List<String> last;
    private float distance;//动画：移动的距离
    private ValueAnimator valueAnimator;
    private float smallWidth = UI.getPx(R.dimen.wpx34);
    private float smallHeight = UI.getPx(R.dimen.wpx47);
    private float bigWidth = UI.getPx(R.dimen.wpx54);
    private float bigHeight = UI.getPx(R.dimen.wpx72);
    private boolean isRelease;//是否释放资源了，如果释放了则不进行绘制等操作了

    public PicNumberView(Context context) {
        this(context, null);
    }

    public PicNumberView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PicNumberView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public PicNumberView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PicNumberView);
        number = typedArray.getInt(R.styleable.PicNumberView_number, 0);
        isRed = typedArray.getBoolean(R.styleable.PicNumberView_number_red, false);
        isBig = typedArray.getBoolean(R.styleable.PicNumberView_number_big, false);
        typedArray.recycle();
        init();
    }

    /**
     * 初始化画笔等
     */
    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        getBitmapFromCache(String.valueOf(number));//为了避免初始化时不显示图片，默认显示数字0的图片，这里需要初始化一下0的图片
        setNumber(number);
    }

    /**
     * 设置数值，没有动画
     *
     * @param theNumber 数值
     */
    public void setNumberWithoutAnim(int theNumber) {
        if (isRelease) return;
        number = theNumber;
        if (number < 0) number = 0;
        current = new ArrayList<>();
        last = new ArrayList<>();
        postInvalidate();
    }

    /**
     * 设置新的数字，如果比旧的数字刚好多1，则显示动画，否则直接设置数字
     *
     * @param theNumber 数字
     */
    public void setNumber(int theNumber) {
        if (isRelease) return;
        if (theNumber - number == 1) {
            addOnePoint();
        } else {
            setNumberWithoutAnim(theNumber);
        }
    }

    /**
     * 数值加一，有动画
     */
    private void addOnePoint() {
        if (isRelease) return;
        number++;
        startAnim();
        postInvalidate();
    }

    /**
     * 开始动画倒计时
     */
    private void startAnim() {
        if (isRelease) return;
        valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(animation -> {
            float value = (float) animation.getAnimatedValue();
            distance = value * viewHeight;
            postInvalidate();
        });
        valueAnimator.setDuration(ANIM_DUR);
        valueAnimator.start();
    }

    /**
     * 获取数字对应的图片资源编号
     *
     * @param number 数字
     * @return 所求
     */
    private int getResId(int number) {
        int[] pics = isRed ? (isBig ? NUMBER_RED_BIG_PIC_RES_ID : NUMBER_RED_PIC_RES_ID) : (isBig ? NUMBER_BLUE_BIG_PIC_RES_ID : NUMBER_BLUE_PIC_RES_ID);
        return pics[number];
    }

    /**
     * 从缓存中获取Bitmap图片
     *
     * @param s 数字字符
     * @return 所求
     */
    private Bitmap getBitmapFromCache(String s) {
        int number = Integer.parseInt(s);
        Bitmap bitmap = arrBitmap[number];
        if (Checker.isNull(bitmap)) {
            bitmap = BitmapFactory.decodeResource(getResources(), getResId(number));
            bitmap = handleBitmap(bitmap, isBig ? bigWidth : smallWidth, isBig ? bigHeight : smallHeight);
            arrBitmap[number] = bitmap;
            if (singleNumberWidth <= 0) singleNumberWidth = bitmap.getWidth();
            if (singleNumberHeight <= 0) singleNumberHeight = bitmap.getHeight();
        }
        return bitmap;
    }

    /**
     * 生成新的Bitmap图片
     *
     * @return 所求
     */
    private Bitmap handleBitmap(Bitmap bitmap, float newWidth, float newHeight) {
        Matrix matrix = new Matrix();//创建一个处理图片的类
        int width = bitmap.getWidth();//获取图片本身的大小(宽)
        int height = bitmap.getHeight();//获取图片本身的大小(高)
        float wS = newWidth / width;//缩放比---->这块注意这个是新的宽度/高度除以旧的宽度
        float hS = newHeight / height;//缩放比---->这块注意这个是新的宽度/高度除以旧的宽度
        matrix.postScale(wS, hS);//这块就是处理缩放的比例
        //matrix.setScale(sX,sY);//缩放图片的质量sX表示宽0.5就代表缩放一半,sX同样
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    /**
     * 释放资源
     */
    public void release() {
        isRelease = true;
        //释放Bitmap图片资源
        if (Checker.notNull(arrBitmap) && arrBitmap.length > 0) {
            for (int i = 0; i < arrBitmap.length; i++) {
                Bitmap bitmap = arrBitmap[i];
                if (Checker.notNull(bitmap) && !bitmap.isRecycled()) {
                    bitmap.recycle();
                    bitmap = null;
                    arrBitmap[i] = null;
                }
            }
        }
        arrBitmap = null;
        if (Checker.notNull(current)) current.clear();
        current = null;
        if (Checker.notNull(last)) last.clear();
        last = null;
        if (Checker.notNull(valueAnimator) && valueAnimator.isRunning())
            valueAnimator.cancel();
        valueAnimator = null;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isRelease) return;
        if (number < 0) return;
        String str = String.valueOf(number);
        viewWidth = str.length() * singleNumberWidth;
        requestLayout();
        int lastNumber = number - 1;
        String lastStr = String.valueOf(lastNumber);
        for (int i = 0; i < str.length(); i++) {
            String s = str.substring(i, i + 1);
            if (i < current.size()) current.set(i, s);
            else current.add(s);
        }
        if (lastNumber >= 0) {
            for (int i = 0; i < lastStr.length(); i++) {
                String s = lastStr.substring(i, i + 1);
                if (i < last.size()) last.set(i, s);
                else last.add(s);
            }
        }
        for (int i = 0; i < str.length(); i++) {//这里的i表示位置（个位、十位），n表示具体是数字几
            if (valueAnimator != null && valueAnimator.isRunning()) {
                if (i < last.size() && i < current.size() && last.get(i).equals(current.get(i))) {//没有变动的位置保持不动
                    canvas.drawBitmap(getBitmapFromCache(current.get(i)), i * singleNumberWidth, 0, paint);
                } else {//有改动的位置开始动画
                    if (i < last.size())
                        canvas.drawBitmap(getBitmapFromCache(last.get(i)), i * singleNumberWidth, 0 - distance, paint);
                    if (i < current.size())//可以不加
                        canvas.drawBitmap(getBitmapFromCache(current.get(i)), i * singleNumberWidth, viewHeight - distance, paint);
                }
            } else {
                LogUtils.e("drawBitmap i=" + i);
                canvas.drawBitmap(getBitmapFromCache(current.get(i)), i * singleNumberWidth, 0, paint);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
    }

    /**
     * 获取宽或者高
     *
     * @param measureSpec 测量单位
     * @param isWidSpec   是宽还是高
     * @return 所求
     */
    private int measure(int measureSpec, boolean isWidSpec) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            viewWidth = String.valueOf(number).length() * singleNumberWidth;
            viewHeight = singleNumberHeight;
            result = isWidSpec ? viewWidth : viewHeight;
            if (mode == MeasureSpec.AT_MOST) result = Math.min(result, size);
        }
        return result;
    }

    @Override
    protected void onDetachedFromWindow() {
        release();//在PK页测试了一下，会在PK页关闭3到5秒内执行这个方法。
        super.onDetachedFromWindow();
    }
}
